package com.itheima.service.impl.ums;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.core.PageInfo;
import com.itheima.mapper.ums.UmsAdminMapper;
import com.itheima.pojo.ums.*;
import com.itheima.pojo.ums.vo.LoginParamVo;
import com.itheima.pojo.ums.vo.UmsAdminVo;
import com.itheima.pojo.ums.vo.UpdatePasswordVo;
import com.itheima.service.ums.*;
import com.itheima.utils.JwtUtil;
import com.itheima.utils.RedisCache;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@DubboService
public class UmsAdminServiceImpl extends ServiceImpl<UmsAdminMapper, UmsAdmin> implements UmsAdminService {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private RedisCache redisCache;
    @DubboReference
    private UmsAdminRoleRelationService umsAdminRoleRelationService;
    @DubboReference
    private UmsRoleService umsRoleService;
    @DubboReference
    private UmsMenuService umsMenuService;
    @DubboReference
    private UmsRoleMenuRelationService umsRoleMenuRelationService;


    /**
     * 登录以后返回token
     *
     * @param loginParamVo
     * @return
     */
    @Override
    public String login(LoginParamVo loginParamVo) {
        //AuthenticationManager authenticationManager进行登录认证
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(loginParamVo.getUsername(), loginParamVo.getPassword());
        Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        //如果认证没通过，给出相应提示
        if (Objects.isNull(authenticate)) {
            throw new RuntimeException("登陆失败");
        }
        //如果认证成功，根据用户id转化成token，然后返回到前端页面
        LoginUms loginUms = (LoginUms) authenticate.getPrincipal();
        String umsId = loginUms.getUmsAdmin().getId().toString();
        String jwt = JwtUtil.createJWT(umsId);
        //把完整的用户信息存入到redis当中
         redisCache.setCacheObject("login:"+umsId,loginUms);
        return jwt;
    }

    /**
     * 获取当前登录用户信息
     *
     * @param name
     * @return
     */
    @Override
    public UmsAdminVo info(String name) {
        LambdaQueryWrapper<UmsAdmin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UmsAdmin::getUsername, name);
        UmsAdmin umsAdmin = this.getOne(queryWrapper);

        //根据admin获取roleid
        LambdaQueryWrapper<UmsAdminRoleRelation> adminRoleRelationLambdaQueryWrapper = new LambdaQueryWrapper<>();
        adminRoleRelationLambdaQueryWrapper.eq(UmsAdminRoleRelation::getAdminId, umsAdmin.getId());
        List<UmsAdminRoleRelation> relationList = umsAdminRoleRelationService.list(adminRoleRelationLambdaQueryWrapper);
        //获取roleids
        List<String> roleNames = relationList.stream().map(item -> {
            UmsRole role = umsRoleService.getById(item.getRoleId());
            return role.getName();
        }).collect(Collectors.toList());

        List<UmsRoleMenuRelation> umsRoleMenuRelations = null;
        for (UmsAdminRoleRelation relation : relationList) {
            LambdaQueryWrapper<UmsRoleMenuRelation> umsRoleMenuRelationLambdaQueryWrapper = new LambdaQueryWrapper<>();
            umsRoleMenuRelationLambdaQueryWrapper.eq(UmsRoleMenuRelation::getRoleId, relation.getRoleId());
            umsRoleMenuRelations = umsRoleMenuRelationService.list(umsRoleMenuRelationLambdaQueryWrapper);
        }

        List<UmsMenu> umsMenuList = umsRoleMenuRelations.stream().map(umsRoleMenuRelation -> {
            UmsMenu umsMenu = umsMenuService.getById(umsRoleMenuRelation.getMenuId());
            return umsMenu;
        }).collect(Collectors.toList());

        //封装数据
        UmsAdminVo umsAdminVo = new UmsAdminVo();
        umsAdminVo.setRoles(roleNames.toArray());
        umsAdminVo.setMenus(umsMenuList);
        umsAdminVo.setUsername(umsAdmin.getUsername());
        umsAdminVo.setIcon(umsAdmin.getIcon());
        return umsAdminVo;
    }


    /**
     * 登出功能
     */
   /* @Override
    public void logout() {
        //获取SecurityContextHolder中的用户id
        UsernamePasswordAuthenticationToken authentication =
                (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LoginUms loginUms =(LoginUms) authentication.getPrincipal();
        Long umsId = loginUms.getUmsAdmin().getId();

        //删除redis中的值
        redisCache.deleteObject("login:"+umsId);

    }*/


    @Override
    public PageInfo pageList( String keyWord, int pageNum, int pageSize) {

        PageInfo pageInfo=new PageInfo();
        LambdaQueryWrapper<UmsAdmin> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.like(keyWord!=null,UmsAdmin::getUsername,keyWord).orderByDesc(UmsAdmin::getCreateTime);
        List<UmsAdmin> list = this.list(queryWrapper);
        pageInfo.setList(list);
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        int total = this.count(queryWrapper);
        pageInfo.setTotal(total);
        Integer totalPage = PageInfo.totalPage(pageSize, total);
        pageInfo.setTotalPage(totalPage);

        return pageInfo;


    }

    @Override
    public List<UmsRole> getRoles(Long adminId) {

        List<UmsRole> umsRoleList=new ArrayList<>();
        LambdaQueryWrapper<UmsAdminRoleRelation> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(adminId!=null,UmsAdminRoleRelation::getAdminId,adminId);
        List<UmsAdminRoleRelation> list = umsAdminRoleRelationService.list(queryWrapper);
        for (UmsAdminRoleRelation umsAdminRoleRelation : list) {
            Long roleId = umsAdminRoleRelation.getRoleId();
            UmsRole umsRole = umsRoleService.getById(roleId);
            umsRoleList.add(umsRole);
        }

        return umsRoleList;
    }

    @Override
    public void roleUpdate(Long adminId, List<Long> roleIds) {
        LambdaQueryWrapper<UmsAdminRoleRelation> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(UmsAdminRoleRelation::getAdminId,adminId);
        List<UmsAdminRoleRelation> list = umsAdminRoleRelationService.list(queryWrapper);
        for (int i = 0; i < list.size(); i++) {
            list.get(i).setRoleId(roleIds.get(i));
            umsAdminRoleRelationService.save(list.get(i));
        }

    }

    @Override
    public void updateAdmin(Long id, UmsAdmin umsAdmin) {
        this.updateById(umsAdmin);
    }

    @Override
    public void updateStatus(Long id, Integer status) {
        UmsAdmin umsAdmin = this.getById(id);
        umsAdmin.setStatus(status);
        this.updateById(umsAdmin);

    }

    @Override
    public UmsAdmin getUmsAdminInfo(Long id) {
        UmsAdmin umsAdmin = this.getById(id);
        return umsAdmin;
    }

    @Override
    public void updatePassword(UpdatePasswordVo updatePasswordVo) {
        LambdaQueryWrapper<UmsAdmin> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(updatePasswordVo.getUsername()!=null,UmsAdmin::getUsername,updatePasswordVo.getUsername());
        UmsAdmin umsAdmin = this.getOne(queryWrapper);
        String oldPassword = updatePasswordVo.getOldPassword();
        BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(oldPassword);
        if (encode.equals(umsAdmin.getPassword())){
            String newEncode = passwordEncoder.encode(updatePasswordVo.getNewPassword());
            umsAdmin.setPassword(newEncode);
        }else{
            //TODO 自定义异常
            System.out.println("密码错误，不可修改");
        }
    }

    @Override
    public void delete(Long id) {
        this.removeById(id);
    }


}
